package tl;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * @program: algorithm
 * @description:
 * @author: 陈恩涛
 * @create: 2022-09-01 10:17
 **/
public class ThreadLocalDemo {

    // 初始化，避免NPE
    private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);

    public static void main(String[] args) {
        // threadLocalStackLeak();
        savePersonalSales();
    }

    private static void savePersonalSales() {
        final House house = new House();
        for (int i = 1; i <= 10; i++) {
            new Thread(() -> {
                final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
                for (int j = 0; j < threadLocalRandom.nextInt(10); j++) {
                    house.saleHouse();
                }
                System.out.println(Thread.currentThread().getName() + "\t卖了" + house.getHouse() + "套房");
            }, String.valueOf(i)).start();
        }
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static void threadLocalStackLeak() {
        // 带来业务问题的案例
        // 在不用线程池，而是自行new Thread时，则可能会产生线程泄露问题
        // 解决方案，每次使用完threadlocal，try{...}finally{threadlocal.remove();}
        final ExecutorService executorService = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            executorService.submit(() -> {
                threadLocal.set(threadLocal.get() + 1);
                System.out.println("更新之后的值" + "\t" + threadLocal.get());
            });
        }
        executorService.shutdown();
    }
}

class House{

    private final static ThreadLocal<Integer> COUNT = ThreadLocal.withInitial(() -> 0);

    public void saleHouse() {
        COUNT.set(1 + COUNT.get());
    }

    public Integer getHouse() {
        return COUNT.get();
    }
}
